home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / dev / c / tox.lha / tox / tox.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-23  |  16.3 KB  |  595 lines

  1. /*-------------------------------------------------------------------------
  2.  * tox - an XML tokenizer
  3.  *
  4.  * Copyright (c) 2000 Eckhart Köppen
  5.  *
  6.  * This library is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU Library General Public
  8.  * License as published by the Free Software Foundation; either
  9.  * version 2 of the License, or (at your option) any later version.
  10.  *
  11.  * This library is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.     See the GNU
  14.  * Library General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU Library General Public
  17.  * License along with this library; if not, write to the
  18.  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  19.  * Boston, MA 02111-1307, USA.
  20.  *-----------------------------------------------------------------------*/
  21.  
  22. /* $Id: tox.c,v 1.18 2000/05/19 14:28:57 koeppen Exp $ */
  23.  
  24. #include "tox.h"
  25.  
  26. #define TYPE_RANGE       0
  27. #define TYPE_EXACT       1
  28. #define TYPE_SPECIAL     2
  29. #define TYPE_END         3
  30.  
  31. #define SPECIAL_SKIP_DTD 0
  32.  
  33. #define RANGE_LETTER     0
  34. #define RANGE_CHAR       1
  35. #define RANGE_WS         2
  36. #define RANGE_NAMECHAR   3
  37. #define RANGE_HEX        4
  38. #define RANGE_DEC        5
  39.  
  40. const char_range range_table[][12] = {
  41.     /* letter */
  42.     {
  43.      {0x0041, 0x005A},
  44.      {0x0061, 0x007A},
  45.      {0x00C0, 0x00D6},
  46.      {0x00D8, 0x00F6},
  47.      {0x00F8, 0x00FF}
  48.      },
  49.     /* character */
  50.     {
  51.      {0x0009, 0x0009},
  52.      {0x000A, 0x000A},
  53.      {0x000D, 0x000D},
  54.      {0x0020, 0x00FF}
  55.      },
  56.     /* whitespace */
  57.     {
  58.      {0x0009, 0x0009},
  59.      {0x000A, 0x000A},
  60.      {0x000D, 0x000D},
  61.      {0x0020, 0x0020},
  62.      },
  63.     /* name character */
  64.     {
  65.      {'.', '.'},
  66.      {'-', '-'},
  67.      {'_', '_'},
  68.      {':', ':'},
  69.      {0x0030, 0x0039},
  70.      {0x0041, 0x005A},
  71.      {0x0061, 0x007A},
  72.      {0x00B7, 0x00B7},
  73.      {0x00C0, 0x00D6},
  74.      {0x00D8, 0x00F6},
  75.      {0x00F8, 0x00FF}
  76.      },
  77.     /* hex numbers */
  78.     {
  79.      {'0', '9'},
  80.      {'a', 'f'},
  81.      {'A', 'F'}
  82.      },
  83.     /* digits */
  84.     {
  85.      {'0', '9'}
  86.      },
  87. };
  88.  
  89. #define ACTION_PUMP_START        1
  90. #define ACTION_TAGNAME_END       2
  91. #define ACTION_ATTRNAME_END      4
  92. #define ACTION_ATTRVAL_END       8
  93. #define ACTION_WORD_END         16
  94. #define ACTION_WS_END           32
  95.  
  96. const state_def state_table[][7] = {
  97.     /*  0: STATE_CONTENT */
  98.     {
  99.      {TYPE_EXACT, (char_t) '<', STATE_STARTTAG_START, 0},
  100.      {TYPE_EXACT, (char_t) '&', STATE_REF_START, 0},
  101.      {TYPE_RANGE, (char_t) RANGE_WS, STATE_WS_CONTENT, ACTION_PUMP_START},
  102.      {TYPE_RANGE, (char_t) RANGE_CHAR, STATE_WORD_CONTENT, ACTION_PUMP_START},
  103.      {TYPE_END, 0, STATE_ERROR, 0}
  104.      },
  105.     /*  1: STATE_STARTTAG_START */
  106.     {
  107.      {TYPE_EXACT, (char_t) '/', STATE_ENDTAG_START, ACTION_PUMP_START},
  108.      {TYPE_EXACT, (char_t) '_', STATE_STARTTAG_NAME, ACTION_PUMP_START},
  109.      {TYPE_EXACT, (char_t) ':', STATE_STARTTAG_NAME, ACTION_PUMP_START},
  110.      {TYPE_EXACT, (char_t) '?', STATE_PI, 0},
  111.      {TYPE_EXACT, (char_t) '!', STATE_MARKUPDECL_START, 0},
  112.      {TYPE_RANGE, (char_t) RANGE_LETTER, STATE_STARTTAG_NAME, ACTION_PUMP_START},
  113.      {TYPE_END, 0, STATE_ERROR, 0}
  114.      },
  115.     /*  2: STATE_REF_START */
  116.     {
  117.      {TYPE_EXACT, (char_t) '_', STATE_REF_NAME, 0},
  118.      {TYPE_EXACT, (char_t) ':', STATE_REF_NAME, 0},
  119.      {TYPE_EXACT, (char_t) '#', STATE_REF_NUMBER, 0},
  120.      {TYPE_RANGE, (char_t) RANGE_LETTER, STATE_REF_NAME, 0},
  121.      {TYPE_END, 0, STATE_ERROR, 0}
  122.      },
  123.     /*  3: STATE_CHARDATA */
  124.     {
  125.      {TYPE_END, 0, STATE_ERROR, 0}
  126.      },
  127.     /*  4: STATE_ENDTAG_START */
  128.     {
  129.      {TYPE_EXACT, (char_t) '_', STATE_ENDTAG_NAME, 0},
  130.      {TYPE_EXACT, (char_t) ':', STATE_ENDTAG_NAME, 0},
  131.      {TYPE_RANGE, (char_t) RANGE_LETTER, STATE_ENDTAG_NAME, 0},
  132.      {TYPE_END, 0, STATE_ERROR, 0}
  133.      },
  134.     /*  5: STATE_STARTTAG_NAME */
  135.     {
  136.      {TYPE_RANGE, (char_t) RANGE_NAMECHAR, STATE_STARTTAG_NAME, 0},
  137.      {TYPE_RANGE, (char_t) RANGE_WS, STATE_STARTTAG_NAMEEND, ACTION_TAGNAME_END},
  138.      {TYPE_EXACT, (char_t) '/', STATE_EMPTYTAG_END, 0},
  139.      {TYPE_EXACT, (char_t) '>', STATE_CONTENT, ACTION_TAGNAME_END},
  140.      {TYPE_END, 0, STATE_ERROR, 0}
  141.      },
  142.     /*  6: STATE_REF_NAME */
  143.     {
  144.      {TYPE_RANGE, (char_t) RANGE_NAMECHAR, STATE_REF_NAME, 0},
  145.      {TYPE_EXACT, (char_t) ';', STATE_CONTENT, 0},
  146.      {TYPE_END, 0, STATE_ERROR, 0}
  147.      },
  148.     /*  7: STATE_ENDTAG_NAME */
  149.     {
  150.      {TYPE_RANGE, (char_t) RANGE_NAMECHAR, STATE_ENDTAG_NAME, 0},
  151.      {TYPE_RANGE, (char_t) RANGE_WS, STATE_ENDTAG_NAMEEND, ACTION_TAGNAME_END},
  152. /*     {TYPE_EXACT, (char_t) '/', STATE_EMPTYTAG_END, 0}, ??? */
  153.      {TYPE_EXACT, (char_t) '>', STATE_CONTENT, ACTION_TAGNAME_END},
  154.      {TYPE_END, 0, STATE_ERROR, 0}
  155.      },
  156.     /*  8: STATE_STARTTAG_NAMEEND */
  157.     {
  158.      {TYPE_RANGE, (char_t) RANGE_WS, STATE_STARTTAG_NAMEEND,  0},
  159.      {TYPE_EXACT, (char_t) '>', STATE_CONTENT,  0},
  160.      {TYPE_EXACT, (char_t) '/', STATE_EMPTYTAG_END, 0},
  161.      {TYPE_EXACT, (char_t) '_', STATE_ATTR_NAME, ACTION_PUMP_START},
  162.      {TYPE_EXACT, (char_t) ':', STATE_ATTR_NAME, ACTION_PUMP_START},
  163.      {TYPE_RANGE, (char_t) RANGE_LETTER, STATE_ATTR_NAME, ACTION_PUMP_START},
  164.      {TYPE_END, 0, STATE_ERROR, 0}
  165.      },
  166.     /*  9: STATE_ENDTAG_NAMEEND */
  167.     {
  168.      {TYPE_RANGE, (char_t) RANGE_WS, STATE_ENDTAG_NAMEEND, 0},
  169.      {TYPE_EXACT, (char_t) '>', STATE_CONTENT, 0},
  170.      {TYPE_END, 0, STATE_ERROR, 0}
  171.      },
  172.     /* 10: STATE_ATTR_NAME */
  173.     {
  174.      {TYPE_RANGE, (char_t) RANGE_NAMECHAR, STATE_ATTR_NAME, 0},
  175.      {TYPE_RANGE, (char_t) RANGE_WS, STATE_ATTR_NAMEEND, ACTION_ATTRNAME_END},
  176.      {TYPE_EXACT, (char_t) '=', STATE_ATTR_VALSTART, ACTION_ATTRNAME_END},
  177.      {TYPE_END, 0, STATE_ERROR, 0}
  178.      },
  179.     /* 11: STATE_ATTR_NAMEEND */
  180.     {
  181.      {TYPE_RANGE, (char_t) RANGE_WS, STATE_ATTR_NAMEEND, 0},
  182.      {TYPE_EXACT, (char_t) '=', STATE_ATTR_VALSTART, 0},
  183.      {TYPE_END, 0, STATE_ERROR, 0}
  184.      },
  185.     /* 12: STATE_ATTR_VALSTART */
  186.     {
  187.      {TYPE_RANGE, (char_t) RANGE_WS, STATE_ATTR_VALSTART, 0},
  188.      {TYPE_EXACT, (char_t) '"', STATE_ATTR_VALDQUOT, 0},
  189.      {TYPE_EXACT, (char_t) '\'', STATE_ATTR_VALSQUOT, 0},
  190.      {TYPE_END, 0, STATE_ERROR, 0}
  191.      },
  192.     /* 13: STATE_ATTR_VALDQUOT */
  193.     {
  194.      {TYPE_EXACT, (char_t) '"', STATE_STARTTAG_NAMEEND, ACTION_ATTRVAL_END},
  195.      {TYPE_EXACT, (char_t) '<', STATE_ERROR, 0},
  196.      {TYPE_EXACT, (char_t) '&', STATE_ATTR_VALDQUOT_REF, ACTION_PUMP_START},
  197.      {TYPE_RANGE, (char_t) RANGE_CHAR, STATE_ATTR_VALDQUOT, ACTION_PUMP_START},
  198.      {TYPE_END, 0, STATE_ERROR, 0}
  199.      },
  200.     /* 14: STATE_EMPTYTAG_END */
  201.     {
  202.      {TYPE_EXACT, (char_t) '>', STATE_CONTENT, 0},
  203.      {TYPE_END, 0, STATE_ERROR, 0}
  204.     },
  205.     /* 15: STATE_ATTR_VALDQUOT_REF */
  206.     {
  207.      {TYPE_EXACT, (char_t) '_', STATE_ATTR_VDQ_REFNAME, 0},
  208.      {TYPE_EXACT, (char_t) ':', STATE_ATTR_VDQ_REFNAME, 0},
  209.      {TYPE_RANGE, (char_t) RANGE_LETTER, STATE_ATTR_VDQ_REFNAME, 0},
  210.      {TYPE_END, 0, STATE_ERROR, 0}
  211.      },
  212.     /* 16: STATE_ATTR_VDQ_REFNAME */
  213.     {
  214.      {TYPE_RANGE, (char_t) RANGE_NAMECHAR, STATE_ATTR_VDQ_REFNAME, 0},
  215.      {TYPE_EXACT, (char_t) ';', STATE_ATTR_VALDQUOT, 0},
  216.      {TYPE_END, 0, STATE_ERROR, 0}
  217.      },
  218.     /* 17: STATE_ATTR_VALSQUOT */
  219.     {
  220.      {TYPE_EXACT, (char_t) '\'', STATE_STARTTAG_NAMEEND, ACTION_ATTRVAL_END},
  221.      {TYPE_EXACT, (char_t) '<', STATE_ERROR, 0},
  222.      {TYPE_EXACT, (char_t) '&', STATE_ATTR_VALSQUOT_REF, ACTION_PUMP_START},
  223.      {TYPE_RANGE, (char_t) RANGE_CHAR, STATE_ATTR_VALSQUOT, ACTION_PUMP_START},
  224.      {TYPE_END, 0, STATE_ERROR, 0}
  225.      },
  226.     /* 18: STATE_ATTR_VALSQUOT_REF */
  227.     {
  228.      {TYPE_EXACT, (char_t) '_', STATE_ATTR_VSQ_REFNAME, 0},
  229.      {TYPE_EXACT, (char_t) ':', STATE_ATTR_VSQ_REFNAME, 0},
  230.      {TYPE_RANGE, (char_t) RANGE_LETTER, STATE_ATTR_VSQ_REFNAME, 0},
  231.      {TYPE_END, 0, STATE_ERROR, 0}
  232.      },
  233.     /* 19: STATE_ATTR_VSQ_REFNAME */
  234.     {
  235.      {TYPE_RANGE, (char_t) RANGE_NAMECHAR, STATE_ATTR_VSQ_REFNAME, 0},
  236.      {TYPE_EXACT, (char_t) ';', STATE_ATTR_VALSQUOT, 0},
  237.      {TYPE_END, 0, STATE_ERROR, 0}
  238.      },
  239.     /* 20: STATE_DTD_START */
  240.     {
  241.      {TYPE_SPECIAL, (char_t) SPECIAL_SKIP_DTD, STATE_CONTENT, 0},
  242.      {TYPE_END, 0, STATE_ERROR, 0}
  243.      },
  244.     /* 21: STATE_MARKUPDECL_START */
  245.     {
  246.      {TYPE_EXACT, (char_t) '-', STATE_COMMENT_START_1ST, 0},
  247.      {TYPE_EXACT, (char_t) 'D', STATE_DOCTYPE_D, 0},
  248.      {TYPE_EXACT, (char_t) '[', STATE_CDATA_BRACKET, 0},
  249.      {TYPE_END, 0, STATE_ERROR, 0}
  250.      },
  251.     /* 22: STATE_CDATA */
  252.     {
  253.      {TYPE_EXACT, (char_t) ']', STATE_CDATA_1ST_BRACKET, 0},
  254.      {TYPE_RANGE, (char_t) RANGE_CHAR, STATE_CDATA, 0},
  255.      {TYPE_END, 0, STATE_ERROR, 0}
  256.      },
  257.     /* 23: STATE_CDATA_1ST_BRACKET */
  258.     {
  259.      {TYPE_EXACT, (char_t) ']', STATE_CDATA_2ND_BRACKET, 0},
  260.      {TYPE_RANGE, (char_t) RANGE_CHAR, STATE_CDATA, 0},
  261.      {TYPE_END, 0, STATE_ERROR, 0}
  262.      },
  263.     /* 24: STATE_CDATA_2ND_BRACKET */
  264.     {
  265.      {TYPE_EXACT, (char_t) '>', STATE_CONTENT, 0},
  266.      {TYPE_EXACT, (char_t) ']', STATE_CDATA_2ND_BRACKET, 0},
  267.      {TYPE_RANGE, (char_t) RANGE_CHAR, STATE_CDATA, 0},
  268.      {TYPE_END, 0, STATE_ERROR, 0}
  269.      },
  270.     /* 25: STATE_PI */
  271.     {
  272.      {TYPE_EXACT, (char_t) '?', STATE_PI_END_QMARK, 0},
  273.      {TYPE_RANGE, (char_t) RANGE_CHAR, STATE_PI, 0},
  274.      {TYPE_END, 0, STATE_ERROR, 0}
  275.      },
  276.     /* 26: STATE_PI_END_QMARK */
  277.     {
  278.      {TYPE_EXACT, (char_t) '>', STATE_CONTENT, 0},
  279.      {TYPE_EXACT, (char_t) '?', STATE_PI_END_QMARK, 0},
  280.      {TYPE_RANGE, (char_t) RANGE_CHAR, STATE_PI, 0},
  281.      {TYPE_END, 0, STATE_ERROR, 0}
  282.      },
  283.     /* 27: STATE_COMMENT */
  284.     {
  285.      {TYPE_EXACT, (char_t) '-', STATE_COMMENT_1ST_DASH, 0},
  286.      {TYPE_RANGE, (char_t) RANGE_CHAR, STATE_COMMENT, 0},
  287.      {TYPE_END, 0, STATE_ERROR, 0}
  288.      },
  289.     /* 28: STATE_COMMENT_1ST_DASH */
  290.     {
  291.      {TYPE_EXACT, (char_t) '-', STATE_COMMENT_2ND_DASH, 0},
  292.      {TYPE_RANGE, (char_t) RANGE_CHAR, STATE_COMMENT, 0},
  293.      {TYPE_END, 0, STATE_ERROR, 0}
  294.      },
  295.     /* 29: STATE_COMMENT_2ND_DASH */
  296.     {
  297.      {TYPE_EXACT, (char_t) '>', STATE_CONTENT, 0},
  298.      {TYPE_END, 0, STATE_ERROR, 0}
  299.      },
  300.     /* 30: STATE_REF_NUMBER */
  301.     {
  302.      {TYPE_EXACT, (char_t) 'x', STATE_REF_HEX_NUMBER_1, 0},
  303.      {TYPE_RANGE, (char_t) RANGE_DEC, STATE_REF_DEC_NUMBER, 0},
  304.      {TYPE_END, 0, STATE_ERROR, 0}
  305.      },
  306.     /* 31: STATE_REF_HEX_NUMBER_1 */
  307.     {
  308.      {TYPE_RANGE, (char_t) RANGE_HEX, STATE_REF_HEX_NUMBER, 0},
  309.      {TYPE_END, 0, STATE_ERROR, 0}
  310.      },
  311.     /* 32: STATE_REF_HEX_NUMBER */
  312.     {
  313.      {TYPE_RANGE, (char_t) RANGE_HEX, STATE_REF_HEX_NUMBER, 0},
  314.      {TYPE_EXACT, (char_t) ';', STATE_CONTENT, 0},
  315.      {TYPE_END, 0, STATE_ERROR, 0}
  316.      },
  317.     /* 33: STATE_REF_DEC_NUMBER */
  318.     {
  319.      {TYPE_RANGE, (char_t) RANGE_DEC, STATE_REF_DEC_NUMBER, 0},
  320.      {TYPE_EXACT, (char_t) ';', STATE_CONTENT, 0},
  321.      {TYPE_END, 0, STATE_ERROR, 0}
  322.      },
  323.     /* 34: STATE_WS_CONTENT */
  324.     {
  325.      {TYPE_EXACT, (char_t) '<', STATE_STARTTAG_START, ACTION_WS_END},
  326.      {TYPE_EXACT, (char_t) '&', STATE_REF_START, ACTION_WS_END},
  327.      {TYPE_RANGE, (char_t) RANGE_WS, STATE_WS_CONTENT, 0},
  328.      {TYPE_RANGE, (char_t) RANGE_CHAR, STATE_WORD_CONTENT, ACTION_PUMP_START | ACTION_WS_END},
  329.      {TYPE_END, 0, STATE_ERROR, 0}
  330.      },
  331.     /* 35: STATE_WORD_CONTENT */
  332.     {
  333.      {TYPE_EXACT, (char_t) '<', STATE_STARTTAG_START, ACTION_WORD_END},
  334.      {TYPE_EXACT, (char_t) '&', STATE_REF_START, ACTION_WORD_END},
  335.      {TYPE_RANGE, (char_t) RANGE_WS, STATE_WS_CONTENT, ACTION_PUMP_START | ACTION_WORD_END},
  336.      {TYPE_RANGE, (char_t) RANGE_CHAR, STATE_WORD_CONTENT, 0},
  337.      {TYPE_END, 0, STATE_ERROR, 0}
  338.      },
  339.     /* 36: STATE_COMMENT_START_1ST */
  340.     {
  341.      {TYPE_EXACT, (char_t) '-', STATE_COMMENT, 0},
  342.      {TYPE_END, 0, STATE_ERROR, 0}
  343.      },
  344.     /* 37: STATE_DOCTYPE_D */
  345.     {
  346.      {TYPE_EXACT, (char_t) 'O', STATE_DOCTYPE_O, 0},
  347.      {TYPE_END, 0, STATE_ERROR, 0}
  348.      },
  349.     /* 38: STATE_DOCTYPE_O */
  350.     {
  351.      {TYPE_EXACT, (char_t) 'C', STATE_DOCTYPE_C, 0},
  352.      {TYPE_END, 0, STATE_ERROR, 0}
  353.      },
  354.     /* 39: STATE_DOCTYPE_C */
  355.     {
  356.      {TYPE_EXACT, (char_t) 'T', STATE_DOCTYPE_T, 0},
  357.      {TYPE_END, 0, STATE_ERROR, 0}
  358.      },
  359.     /* 40: STATE_DOCTYPE_T */
  360.     {
  361.      {TYPE_EXACT, (char_t) 'Y', STATE_DOCTYPE_Y, 0},
  362.      {TYPE_END, 0, STATE_ERROR, 0}
  363.      },
  364.     /* 41: STATE_DOCTYPE_Y */
  365.     {
  366.      {TYPE_EXACT, (char_t) 'P', STATE_DOCTYPE_P, 0},
  367.      {TYPE_END, 0, STATE_ERROR, 0}
  368.      },
  369.     /* 42: STATE_DOCTYPE_P */
  370.     {
  371.      {TYPE_EXACT, (char_t) 'E', STATE_DTD_START, 0},
  372.      {TYPE_END, 0, STATE_ERROR, 0}
  373.      },
  374.     /* 43: STATE_CDATA_BRACKET */
  375.     {
  376.      {TYPE_EXACT, (char_t) 'C', STATE_CDATA_C, 0},
  377.      {TYPE_END, 0, STATE_ERROR, 0}
  378.      },
  379.     /* 44: STATE_CDATA_C */
  380.     {
  381.      {TYPE_EXACT, (char_t) 'D', STATE_CDATA_D, 0},
  382.      {TYPE_END, 0, STATE_ERROR, 0}
  383.      },
  384.     /* 45: STATE_CDATA_D */
  385.     {
  386.      {TYPE_EXACT, (char_t) 'A', STATE_CDATA_A, 0},
  387.      {TYPE_END, 0, STATE_ERROR, 0}
  388.      },
  389.     /* 46: STATE_CDATA_A */
  390.     {
  391.      {TYPE_EXACT, (char_t) 'T', STATE_CDATA_T, 0},
  392.      {TYPE_END, 0, STATE_ERROR, 0}
  393.      },
  394.     /* 47: STATE_CDATA_T */
  395.     {
  396.      {TYPE_EXACT, (char_t) 'A', STATE_CDATA_A2, 0},
  397.      {TYPE_END, 0, STATE_ERROR, 0}
  398.      },
  399.     /* 48: STATE_CDATA_A2 */
  400.     {
  401.      {TYPE_EXACT, (char_t) '[', STATE_CDATA, 0},
  402.      {TYPE_END, 0, STATE_ERROR, 0}
  403.      },
  404. };
  405.  
  406. int range_match (int range, char_t c);
  407. void skip_dtd (parser_state *);
  408. void action (parser_state *, int);
  409.  
  410. void tagname_end (parser_state *parser);
  411. void attrname_end (parser_state *parser);
  412. void attrval_end (parser_state *parser);
  413. void word_end (parser_state *parser);
  414. void ws_end (parser_state *parser);
  415.  
  416. int range_match (int range, char_t c)
  417. {
  418.     int i, r;
  419.  
  420.     r = 0;
  421.     for (i = 0; range_table[range][i].start > 0; i++) {
  422.         if (range_table[range][i].start <= c
  423.             && c <= range_table[range][i].end) {
  424.             r = 1;
  425.         }
  426.     }
  427.     return r;
  428. }
  429.  
  430. void skip_dtd (parser_state *parser)
  431. {
  432.     while (parser->current < parser->maxtext &&
  433.            parser->angleBracketLevel > -1) {
  434.         switch (parser->text[parser->current]) {
  435.         case '<':
  436.             if (parser->squoteLevel == 0 && parser->dquoteLevel == 0)
  437.                 parser->angleBracketLevel++;
  438.             break;
  439.         case '>':
  440.             if (parser->squoteLevel == 0 && parser->dquoteLevel == 0)
  441.                 parser->angleBracketLevel--;
  442.             break;
  443.         case '"':
  444.             if (parser->dquoteLevel > 0)
  445.                 parser->dquoteLevel--;
  446.             else if (parser->squoteLevel == 0)
  447.                 parser->dquoteLevel++;
  448.             break;
  449.         case '\'':
  450.             if (parser->squoteLevel > 0)
  451.                 parser->squoteLevel--;
  452.             else if (parser->dquoteLevel == 0)
  453.                 parser->squoteLevel++;
  454.             break;
  455.         }
  456.         if (parser->angleBracketLevel > -1) parser->current++;
  457.     }
  458. }
  459.  
  460. void tagname_end (parser_state *parser)
  461. {
  462.     parser->pump = 0;
  463.     parser->buffer[parser->bcurrent] = '\0';
  464.     parser->bcurrent = 0;
  465.     if (parser->element_callback) (parser->element_callback)(parser);
  466. }
  467.  
  468. void attrname_end (parser_state *parser)
  469. {
  470.     parser->pump = 0;
  471.     parser->buffer[parser->bcurrent] = '\0';
  472.     parser->bcurrent = 0;
  473.     if (parser->attrname_callback) (parser->attrname_callback)(parser);
  474. }
  475.  
  476. void attrval_end (parser_state *parser)
  477. {
  478.     parser->pump = 0;
  479.     parser->buffer[parser->bcurrent] = '\0';
  480.     parser->bcurrent = 0;
  481.     if (parser->attrval_callback) (parser->attrval_callback)(parser);
  482. }
  483.  
  484. void word_end (parser_state *parser)
  485. {
  486.     parser->pump = 0;
  487.     parser->buffer[parser->bcurrent] = '\0';
  488.     parser->bcurrent = 0;
  489.     if (parser->word_callback) (parser->word_callback)(parser);
  490. }
  491.  
  492. void ws_end (parser_state *parser)
  493. {
  494.     parser->pump = 0;
  495.     parser->buffer[parser->bcurrent] = '\0';
  496.     parser->bcurrent = 0;
  497.     if (parser->ws_callback) (parser->ws_callback)(parser);
  498. }
  499.  
  500. void action (parser_state *parser, int variant)
  501. {
  502.     unsigned int action;
  503.     
  504.     action = state_table[parser->state][variant].action;
  505.     if (action & ACTION_TAGNAME_END) tagname_end (parser);
  506.     if (action & ACTION_ATTRNAME_END) attrname_end (parser);
  507.     if (action & ACTION_ATTRVAL_END) attrval_end (parser);
  508.     if (action & ACTION_WORD_END) word_end (parser);
  509.     if (action & ACTION_WS_END) ws_end (parser);
  510.     if (action & ACTION_PUMP_START) parser->pump = 1;
  511. }
  512.  
  513. void tox_parse (parser_state *parser)
  514. {
  515.     char_t c;
  516.     int i, transition;
  517.     
  518.     while (parser->current < parser->maxtext &&
  519.         parser->state != STATE_ERROR && parser->state != STATE_END) {
  520.         c = parser->text[parser->current];
  521.  
  522.         /*
  523.           printf ("%d %3.3s\n", parser->state,
  524.           &parser->text[parser->current]);
  525.         */
  526.  
  527.         transition = 0;
  528.         for (i = 0; !transition && parser->state != STATE_ERROR; i++) {
  529.             switch (state_table[parser->state][i].accept_type) {
  530.             case TYPE_EXACT:
  531.                 if ((unsigned int) state_table[parser->state][i].accept_value == (unsigned int) c) {
  532.                     transition = 1;
  533.                     action (parser, i);
  534.                     parser->state = state_table[parser->state][i].next_state;
  535.                 }
  536.                 break;
  537.             case TYPE_RANGE:
  538.                 if (range_match
  539.                     ((int) state_table[parser->state][i].accept_value, c)) {
  540.                     transition = 1;
  541.                     action (parser, i);
  542.                     parser->state = state_table[parser->state][i].next_state;
  543.                 }
  544.                 break;
  545.             case TYPE_SPECIAL:
  546.                 switch ((int) state_table[parser->state][i].accept_value) {
  547.                     case SPECIAL_SKIP_DTD:
  548.                         skip_dtd (parser);
  549.                         transition = 1;
  550.                         if (parser->angleBracketLevel == -1) {
  551.                             parser->state = state_table[parser->state][i].next_state;
  552.                             parser->squoteLevel = 0;
  553.                             parser->dquoteLevel = 0;
  554.                             parser->angleBracketLevel = 0;
  555.                         }
  556.                         break;
  557.                 }
  558.                 break;
  559.             case TYPE_END:
  560.                 parser->state = STATE_ERROR;
  561.                 break;
  562.             }
  563.         }
  564.  
  565.         if (parser->pump && parser->bcurrent < parser->maxbuf) {
  566.             parser->buffer[parser->bcurrent++] = c;
  567.         }
  568.  
  569.         parser->current++;
  570.     }
  571. }
  572.  
  573. int tox_wstrcmp (char_t *s1, char *s2)
  574. {
  575.     while (*s1 && *s2 && *s1 == *s2) {
  576.         s1++;
  577.         s2++;
  578.     }
  579.     return *s2 ? *s1 - *s2 : 0;
  580. }
  581.  
  582. int tox_strlen (char *s)
  583. {
  584.     int i = 0;
  585.     while (s[i++]) ;
  586.     return i - 1;
  587. }
  588.  
  589. /*
  590.  * Local variables:
  591.  * c-basic-offset: 4
  592.  * tab-width: 4
  593.  * End:
  594.  */
  595.